<template>
  <div class="maincon">
    <div :class="$attrs?.horizontalShowBtns ? 'h-funs' : 'funs'" v-if="!power('query')">
      <slot name="querydata">
        <div class="query-top" v-if="isQueryH">
          <query :queryInfo="queryInfo" :queryLabel="queryLabel" :queryLabelWidth="queryLabelWidth" :justify="justify"
            @refersh="() => get_data_list()" :moreState="(a) => a !== true">
            <template v-for="(_, name) in $scopedSlots" v-slot:[name]="data">
              <slot :name="name" v-bind="data"></slot>
            </template>
            <template #more>
              <div style="display: inline-flex;align-items: center;padding-bottom: 3px;">
                <div @click="more()" style="display: inline-flex; margin-left: 10px" v-if="power('more')">
                  <slot name="more">
                    <el-button v-bind="btnAttrs('more')" v-if="power('more')">{{ globlSetting.more.text }}</el-button>
                  </slot>
                </div>
                <el-popover placement="bottom-start" trigger="click" v-if="power('more1')" :width="popoverWidth"
                  :offset="popoverOffset" style="margin-left: 10px">
                  <template #reference>
                    <slot name="more1">
                      <el-button v-bind="btnAttrs('more')" v-if="power('more1')">{{ globlSetting.more.text
                      }}</el-button>
                    </slot>
                  </template>
                  <div class="more" ref="more" id="more">
                    <div style="display: flex; flex-wrap: wrap; flex: 1" v-if="isQueryH">
                      <query :queryInfo="queryInfo" style="width: 100%" :queryLabel="queryLabel"
                        :queryLabelWidth="queryLabelWidth" :justify="justify" @refersh="() => get_data_list()"
                        :moreState="(a) => a === true">
                        <template v-for="(_, name) in $scopedSlots" v-slot:[name]="data">
                          <slot :name="name" v-bind="data"></slot>
                        </template>
                      </query>
                    </div>
                  </div>
                </el-popover>
              </div>
            </template>
            <template #query>
              <div style="
                  display: inline-flex;
                  align-items: center;
                  padding-bottom: 3px;
                ">
                <div @click="get_data_list()" style="display: inline-flex; margin-left: 10px">
                  <slot name="query" v-if="isQueryH && showLeftQuery">
                    <el-button v-bind="btnAttrs('search')">{{ globlSetting.search.text }}</el-button>
                  </slot>
                </div>
              </div>
            </template>
          </query>
        </div>
      </slot>
      <div class="query-btns">
        <div class="query-btns-left">
          <slot name="addleft"> </slot>
          <div @click="get_data_list()" style="display: inline-flex; margin-right: 10px">
            <slot name="query" v-if="isQueryH && !showLeftQuery">
              <el-button v-bind="btnAttrs('search')">{{ globlSetting.search.text }}</el-button>
            </slot>
          </div>
          <slot name="batch" :info="selectedRows" v-if="power('batch')">
            <el-button @click="batchHandle" v-bind="btnAttrs('batch')" style="margin-right: 10px !important">{{
              batchName
            }}</el-button>
          </slot>
          <slot name="add" v-if="!power('add') && qx({}).add()">
            <el-button @click="add" v-bind="btnAttrs('add')" style="margin-left: 0px; margin-right: 10px !important">{{
              globlSetting.add.text }}</el-button>
          </slot>
          <div style="display: inline-flex" @click="open_set()">
            <slot name="setting" v-if="power('setting')">
              <el-button style="margin-right: 10px" v-bind="btnAttrs('setting')">
                {{ globlSetting.setting.text }}
              </el-button>
            </slot>
          </div>
          <slot name="addright"> </slot>
        </div>
        <slot name="query-btns-right"></slot>
      </div>
    </div>
    <!--more 水平样式查询-->
    <div class="more" v-if="isMore && power('more')" ref="more" id="more">
      <div style="display: flex; flex-wrap: wrap; flex: 1" v-if="isQueryH">
        <query :queryInfo="queryInfo" style="width: 100%" :queryLabel="queryLabel" :queryLabelWidth="queryLabelWidth"
          :justify="justify" @refersh="() => get_data_list()" :moreState="(a) => a === true">
          <template v-for="(_, name) in $scopedSlots" v-slot:[name]="data">
            <slot :name="name" v-bind="data"></slot>
          </template>
        </query>
      </div>
    </div>
    <!--more 垂直样式查询  $attrs.attrs && $attrs.attrs['min-height'] ? `min-height:${$attrs.attrs['min-height']}` : `height:${tempHeight}`-->
    <div class="tabcon" :style="setStyle" id="tempHeight">
      <div :style="`border-top:1px solid #EBEEF5;display: flex;flex-direction:column;width: ${isExpand ? leftWidth + 'px' : '23px'
        }`" v-if="!isQueryH && !power('query')">
        <div style="display: flex; height: 39px; align-items: center">
          <div style="display: flex; flex: 1; margin-left: 5px" v-if="isExpand">
            搜索
          </div>
          <div style="display: flex; justify-content: flex-end">
            <i class="el-icon-s-fold" @click="toggleQuery(true)" v-if="isExpand"
              style="font-size: 22px; cursor: pointer"></i>
            <i class="el-icon-s-unfold" @click="toggleQuery(false)" style="font-size: 22px; cursor: pointer" v-else></i>
          </div>
        </div>
        <div style="padding: 0 0 3px 3px" v-if="isExpand">
          <query :queryInfo="queryInfo" style="width: 100%" :queryLabel="queryLabel" :queryLabelWidth="queryLabelWidth"
            :justify="justify" @refersh="() => get_data_list()" :moreState="() => true">
            <template v-for="(_, name) in $scopedSlots" v-slot:[name]="data">
              <slot :name="name" v-bind="data"></slot>
            </template>
          </query>
          <div style="display: flex; padding: 10px; justify-content: center">
            <div @click="get_data_list()" style="height: 100%; padding: 0 10px">
              <slot name="query">
                <el-button v-bind="btnAttrs('search')">{{ globlSetting.search.text }}</el-button>
              </slot>
            </div>
          </div>
        </div>
      </div>
      <!--table 表格-->
      <div id="gyc-table" :style="`display: flex;width:${isQueryH || power('query')
        ? '100%'
        : `${isExpand
          ? 'calc(100% - ' + leftWidth + 'px)'
          : 'calc(100% - 23px)'
        }`
        };`">
        <slot name="g-table">
          <el-form ref="ruleForm" style="width: 100% !important" :status-icon="true" :model="tableData"
            :validate-on-rule-change="false" :show-message="showMessage">
            <el-table ref="baseTable" :data="tableData.ruleData"  :row-class-name="rowClassName"
              :row-style="rowStyle" :cell-style="cellStyle" :cell-class-name="cellClassName"
              :show-summary="sumData === undefined ? false : true" :summary-method="CommSum" @select="tableSelect"
              @select-all="selectAll" @selection-change="selectionChange" @header-dragend="handledrag"
              @sort-change="hand_order" @expand-change="expandChange" @row-click="rowClick" @row-dblclick="rowDbClick"
              v-bind="{...defaultTableAttrs,...$attrs?.attrs}" v-on="$listeners">
              <el-table-column v-for="(item, index) in tempTableAttrs.filter(
                (a) => a.type == 'index' || a.type == 'selection'
              )" :key="`${index}-gyc-selection`" :type="item['type']" v-bind="columnsAttrs(item, 1)">
              </el-table-column>
              <el-table-column v-for="(item, index) in tempTableAttrs.filter(
                (a) => a.type == 'expand'
              )" :key="`${index}-gyc-expand`" type="expand" v-bind="columnsAttrs(item, 1)">
                <template slot-scope="scope">
                  <slot :name="item.key" :info="scope.row"></slot>
                </template>
              </el-table-column>

              <template v-for="item in tempTableAttrs">
                <el-table-column v-bind="columnsAttrs(item, 2)" :sortable="item['sortable'] !== false"
                  :fixed="item['fixed']" :resizable="item['resizable'] === undefined ? true : item['resizable']
                    " v-if="item.visible !== false && item['type'] === undefined"
                  :filters="item['filters'] ? filters(item) : undefined" :filter-method="item['filters'] === undefined &&
                    item['filterMethod'] === undefined
                    ? undefined
                    : (value, row, column) =>
                      filterMethod(value, row, column, item)
                    ">
                  <template slot="header">
                    <slot :name="`header-${item.key}`" :info="item"></slot>
                  </template>

                  <template slot-scope="scope">
                    <slot :name="item.key" :info="scope.row" v-if="editTable && item['editTable']">
                      <el-form-item :prop="scope.$index !== 0
                        ? `ruleData.${scope.$index}.${item.key}`
                        : ''
                        " :rules="init_rules(item, scope.row)" v-if="item.edit !== false" label-width="20px">
                        <editTableItem :item="item" :scope="scope">
                          <template v-for="(_, name) in $scopedSlots" v-slot:[name]="data">
                            <slot :name="name" v-bind="data"></slot>
                          </template>
                        </editTableItem>
                      </el-form-item>
                    </slot>
                    <slot :name="item.key" :info="scope.row" v-else>
                      <table-format-cell :item="item" :scope="scope"></table-format-cell>
                    </slot>
                  </template>

                  <template v-if="item.children">
                    <template v-for="li in item.children">
                      <el-table-column :prop="li.key" :label="li.title" :column-key="Math.random().toString()"
                        :header-align="li['headerAlign'] ? li['headerAlign'] : 'center'
                          " :width="h_width(li)" :align="!li['align'] ? 'center' : li['align']"
                        :sortable="li['sortable'] !== false" :fixed="li['fixed']"
                        v-if="li.visible !== false && li['type'] === undefined">
                        <template slot="header">
                          <slot :name="`header-${li.key}`" :info="li"></slot>
                        </template>

                        <template slot-scope="scope">
                          <slot :name="li.key" :info="scope.row">
                            <table-format-cell :item="li" :scope="scope"></table-format-cell>
                          </slot>
                        </template>
                      </el-table-column>
                    </template>
                  </template>
                </el-table-column>
              </template>
              <el-table-column label="操作" :align="'center'" :width="btnsWidth ? btnsWidth : undefined"
                :fixed="isLockRight" v-if="!power('control') && qx({}).control()">
                <template slot-scope="scope">
                  <div :style="`display: flex;justify-content: ${doControlAlign()};align-items: center;`">
                    <slot name="lbtn" :info="scope.row" :scope="scope" style="display: flex"></slot>
                    <slot name="save" :info="scope.row" v-if="!power('save') && qx(scope.row).save() && editTable">
                      <div style="margin-right: 2px">
                        <el-button v-bind="btnAttrs('save')" @click.stop="lineAdd(scope.row, scope.$index)">
                          {{ globlSetting.save.text }}
                        </el-button>
                      </div>
                    </slot>
                    <slot name="read" :info="scope.row" v-if="!power('read') && qx(scope.row).read()">
                      <div style="margin-right: 10px">
                        <el-button v-bind="btnAttrs('read')" @click="read(scope.row)">
                          {{ globlSetting.read.text }}
                        </el-button>
                      </div>
                    </slot>
                    <slot name="edit" :info="scope.row" :scope="scope"
                      v-if="!power('edit') && qx(scope.row).edit() && !editTable">
                      <div style="margin-right: 10px">
                        <el-button v-bind="btnAttrs('edit')" @click="edit(scope.row, scope.$index)">{{
                          globlSetting.edit.text }}</el-button>
                      </div>
                    </slot>
                    <slot name="del" :info="scope.row" :scope="scope" v-if="
                      editTable
                        ? !power('del') &&
                        qx(scope.row).del() &&
                        scope.$index !== 0
                        : !power('del') && qx(scope.row).del()
                    ">
                      <div style="margin-right: 2px">
                        <el-button v-bind="btnAttrs('del')" @click.stop="deleteData(scope)">{{
                          globlSetting.del.text }}</el-button>
                      </div>
                    </slot>
                    <slot name="rbtn" :info="scope.row" :scope="scope" style="display: flex"></slot>
                  </div>
                </template>
              </el-table-column>
            </el-table>
          </el-form>
        </slot>
      </div>
    </div>
    <slot name="sum"></slot>
    <!--page 分页-->
    <slot name="page">
      <div class="gpage" :style="`justify-content:${doPageAlign()};`" v-if="!power('page')">
        <el-pagination background @size-change="handleSizeChange" @current-change="handleCurrentChange"
          :current-page="page" :page-sizes="pagesizeList" :page-size="pagesize"
          layout="total, sizes, prev, pager, next, jumper" :total="totalcount">
        </el-pagination>
      </div>
    </slot>
    <!--more 表格列设置-->
    <com-set :col-keys="convertFormList().filter((a) => a.visible !== false)" :is="show_set" @close="setClose"
      @set-col-val="setColVal" @set-load="setLoad" @set-drag="setDrag" @lock-right="lockRight" @lock-left="lockLeft"
      @row-reset="rowReset" :set-width="() => setWidth(this)" :show-right="power('control') === false"></com-set>
  </div>
</template>

<script>
import dragable from "sortablejs";
import dayjs from "dayjs";
import opt from "./optimize";
import query from "./query.vue";
import editTableItem from "./edit-table-item.vue";
import TableFormatCell from "./table-format-cell.vue";
import { init_rules } from "./comm.js";
import { createForm, hasHorizontalScrollbar } from "./tools";
import bus from "./bus";
export default {
  name: "g-table",
  components: {
    "com-set": () => import("./columns-setting.vue"),
    query,
    editTableItem,
    TableFormatCell,
  },
  props: {
    //表格columns属性
    tableAttrs: { type: Object, default: () => { } },
    //表格自动高度
    height: { type: String, default: "100" },
    //表格固定高度
    fixedHeight: { type: String, default: undefined },
    //列表操作列宽度
    btnsWidth: { type: Number, default: 185 },
    //排序
    sort: {
      type: Object,
      default: () => undefined,
    },
    //分页显示方式 center|flex-start|flex-end
    page_align: {
      type: Function,
      default: (a) => {
        if (a?.globlSetting?.page_align) {
          return a.globlSetting?.page_align();
        } else {
          return "right";
        }
      },
    },
    //增加或去掉功能
    disFuncs: { type: Array, default: () => [] },
    //页面后缀
    suffix: { type: String, default: "" },
    //操作按钮样式
    btnTypes: {
      type: Object,
      default: (a) => { },
    },
    //行拖拽
    row_Drop: { Boolean, default: false },
    //查询信息
    queryInfo: {
      type: Object, default: () => { }
    },
    //横像查询
    queryH: { type: Boolean, default: true },
    //左侧查询宽度 竖形查询时有效
    leftWidth: { type: Number, default: 200 },
    //是否显示查询label
    queryLabel: { Boolean, default: true },
    //查询label宽度
    queryLabelWidth: {
      type: Function,
      default: (a) => {
        if (a.globlSetting?.queryLabelWidth) {
          return a.globlSetting.queryLabelWidth(a);
        } else {
          return 0;
        }
      },
    },
    //查询输入框宽度
    queryInputWidth: {
      type: Function,
      default: (a) => {
        if (a.globlSetting?.queryInputWidth) {
          return a.globlSetting.queryInputWidth(a);
        } else {
          return 0;
        }
      },
    },
    //查询lable分散对齐
    justify: {
      type: Function,
      default: (a) => {
        if (a?.globlSetting?.queryLabelJustify) {
          return a?.globlSetting?.queryLabelJustify();
        } else {
          return false;
        }
      },
    },
    //查询弹窗宽度
    popoverWidth: { type: String, default: "150px" },
    //查询弹窗偏移量
    popoverOffset: { type: Number, default: 0 },
    //合计数据
    sumData: { type: Object, default: () => { } },
    //行的 className 的回调方法
    rowClassName: { type: Function, default: () => { } },
    //行的 style 的回调方法
    rowStyle: {
      type: Function,
      default: () => {
        return { cursor: "pointer" };
      },
    },
    //单元格的 className 的回调方法
    cellClassName: { type: Function, default: () => { } },
    //单元格的 style 的回调方法
    cellStyle: { type: Function, default: () => { } },
    //页数据条数
    pagesizeList: { type: Array, default: () => [5, 10, 15, 20, 50, 100] },
    "set-width": {
      type: Function,
      default: (a) => {
        if (a?.globlSetting?.setWidth) {
          return a?.globlSetting?.setWidth();
        } else {
          return "584px";
        }
      },
    },
    //批处理按钮名称
    batchName: { type: String, default: "批量处理" },
    //开启表格编辑
    editTable: { type: Boolean, default: false },
    //表格编辑时，是否显示验证错误消息
    "show-message": { type: Boolean, default: false },
    //操作列对齐方式样式
    "control-align": {
      type: Function,
      default: (a) => {
        if (a?.globlSetting?.controlAlign) {
          return a?.globlSetting?.controlAlign();
        } else {
          return "center";
        }
      },
    },
    //表格默认宽度
    "d-width": {
      type: Function,
      default: (a) => {
        if (a?.globlSetting?.dWidth) {
          return a?.globlSetting?.dWidth();
        } else {
          return "30px";
        }
      },
    },
    //表格是否拖拽
    resizable: { type: Boolean, default: true },
    showLeftQuery: { type: Boolean, default: true },
  },
  data() {
    return {
      btnAttrs: (key) => {
        return {
          icon: this.globlSetting[key].icon,
          type: this.globlSetting[key].type,
          plain: this.globlSetting[key].plain,
          round: this.globlSetting[key].round,
          size: this.globlSetting[key].size,
          circle: this.globlSetting[key].circle,
          style: this.globlSetting[key].style,
        };
      },
      page: 1,
      pagesize: this.globlSetting?.pagesize ? this.globlSetting.pagesize() : 10,
      totalcount: 0,
      tableData: {
        ruleData: [],
      },
      widths: [],
      isExpand: true,
      tempTableAttrs: [],
      isMore: false,
      tempHeight: "",
      show_set: undefined,
      selectedRows: [],
      isQueryH: true,
      columnsAttrs: (item, num = 1) => {
        return Object.assign(
          {
            prop: item.key,
            label: item.title,
            "column-key": Math.random().toString(),
            "header-align": item["headerAlign"]
              ? item["headerAlign"]
              : "center",
            fixed: item["fixed"],
            width: num == 1 ? this.h_width(item, "60px") : this.h_width(item),
            align: !item["align"] ? "center" : item["align"],
          },
          item?.attrs
        );
      },
      isLockRight: false,
      editIndex: -1,
      defaultTableAttrs: {
        stripe: true, 'highlight-current-row': true, height: "100%", style: "width: 100%",border:true
      }
    };
  },
  methods: {
    rowClick(row) {
      this.editIndex = row.__index;
      this.$emit('g-row-click', row)
    },
    rowDbClick(row, column, event) {
      let isExcuteClick = false;
      this.$emit("g-row-dblclick", { row, column, event }, (result = 'read') => {
        isExcuteClick = true;
        if (result == 'read') {
          this.read(row)
        } else if (result == 'edit') {
          this.edit(row)
        } else {
          if (typeof result === 'function') {
            result();
          }
        }
      })
      if (isExcuteClick == false) {
        let f = this.globlSetting.defaultDbClickFunc;
        if (f == 'edit') {
          this.edit(row);
        } else if (f == 'read') {
          this.read(row)
        }
      }
    },
    //处理表格数据属性
    convertFormList() {
      let data = Object.entries(this.tableAttrs).map((a) => {
        let obj = a[1];
        obj.key = a[0];
        return obj;
      });
      return data;
    },
    //处理查询属性
    convertQueryList() {
      if (this.queryInfo) {
        let arr = Object.entries(this.queryInfo);
        if (arr.length > 0) {
          let data = arr.map((a) => {
            let obj = a[1];
            obj.key = a[0];
            return obj;
          });
          return data;
        } else {
          return []
        }
      } else {
        return []
      }
    },
    //设置权限
    qx(row) {
      let qxlist = { read: () => false, add: () => true, edit: () => true, del: () => true, save: () => false, control: () => true };
      this.$emit("qx", row, (list = {}) => {
        qxlist = Object.assign(qxlist, list);
      });
      return qxlist;
    },
    //行拖拽
    rowDrop() {
      // 首先获取需要拖拽的dom节点
      try {
        const el1 = document
          .querySelectorAll(".el-table__body-wrapper")[0]
          .querySelectorAll("table > tbody")[0];
        dragable.create(el1, {
          disabled: false, // 是否开启拖拽
          ghostClass: "sortable-ghost", //拖拽样式
          animation: 150, // 拖拽延时，效果更好看
          group: {
            // 是否开启跨表拖拽
            pull: false,
            put: false,
          },
          onEnd: (e) => {
            let { newIndex, oldIndex } = e;
            // 这里主要进行数据的处理，拖拽实际并不会改变绑定数据的顺序，这里需要自己做数据的顺序更改
            this.$emit("row-drop", { newIndex, oldIndex });
          },
        });
      } catch (error) {
        console.log(error);
      }
    },
    //过滤功能
    power(name) {
      return this.disFuncs.some((a) => a === name);
    },
    //加载列表
    async get_data_list(obj = {}, page = 1) {
      if (page == 1) {
        this.page = 1;
      } else {
        this.page = page;
      }
      let temp = {};
      if (this.queryInfo) {
        temp = Object.fromEntries(
          Object.entries(this.queryInfo)?.filter((a) => a[1]["daterange"] != true)?.map((a) => [a[0], a[1].val])
        );
      }
      let param = Object.assign(
        temp,
        {
          page: page,
          pagesize: localStorage.getItem(
            `${this.$route?.name}-size-${this.suffix}`
          )
            ? parseInt(
              localStorage.getItem(`${this.$route?.name}-size-${this.suffix}`)
            )
            : this.pagesize,
        },
        obj
      );
      let times = this.convertQueryList().filter((a) => a["daterange"] == true);
      let lastdata = param;
      try {
        if (times && times.length > 0) {
          times.forEach((element, index) => {
            lastdata = Object.assign(
              param,
              Object.fromEntries([
                [
                  element["keys"][0],
                  times[index]["vals"] == null
                    ? undefined
                    : times[index]["vals"][0]
                      ? dayjs(times[index]["vals"][0]).format("YYYY-MM-DD")
                      : "",
                ],
              ]),
              Object.fromEntries([
                [
                  element["keys"][1],
                  times[index]["vals"] == null
                    ? undefined
                    : times[index]["vals"][1]
                      ? dayjs(times[index]["vals"][1]).format("YYYY-MM-DD")
                      : "",
                ],
              ])
            );
          });
        }
      } catch (error) {
        console.log(error);
      }
      this.$emit("load", lastdata, (data, total, findItem) => {
        let firstCol = Object.fromEntries(
          this.convertFormList().map((a) => [a.key, a.val])
        );
        firstCol.editRow = true;
        if (this.editTable) {
          this.tableData.ruleData = [firstCol, ...data];
        } else {
          this.tableData.ruleData = data;
        }
        if (this.tableData.ruleData.length > 0) {
          this.tableData.ruleData.forEach((element, index) => {
            this.$set(element, '__index', index)
          });
        }
        this.totalcount = total;
        this.$nextTick(() => {
          this.selectedRows.forEach((item) => {
            if (item.index == lastdata.page) {
              item.data.forEach((i) => {
                this.$refs.baseTable.toggleRowSelection(
                  this.tableData.ruleData.find((li) => findItem(li, i)),
                  true
                );
              });
            }
          });
        });
      }, this);
    },
    //设置页容量
    async handleSizeChange(val) {
      let t = `${this.$route?.name}-size-${this.suffix}`;
      localStorage.setItem(t, val);
      this.debounce(() => this.globlSetting?.saveCache(t, val), 500);
      this.page = 1;
      this.pagesize = val;
      await this.get_data_list();
      this.$emit("changeSize", val, this.tableData.ruleData);
    },
    //下一页
    async handleCurrentChange(val) {
      this.page = val;
      await this.get_data_list({}, val);
      this.$emit("nextPage", val, this.tableData.ruleData);
    },
    //删除
    deleteData(data) {
      this.$confirm("是否要删除这条记录？", "提示消息", {
        roundButton: true,
        iconClass: "el-icon-question",
      })
        .then(() => {
          this.$emit("del", data.row, (res) => {
            if (res === true) {
              if (this.tableData.ruleData.length > 1) {
                this.tableData.ruleData.splice(data.$index, 1);
                this.totalcount -= 1;
              } else {
                this.page = 1;
                this.get_data_list();
              }
            } else {
              this.$message.error(res);
            }
          });
        })
        .catch(() => {
          console.log("cancel");
        });
    },
    //新增
    add() {
      if (this.editTable) {
        let t = Object.fromEntries(
          this.convertFormList().map((a) => [a.key, a.val])
        );
        this.tableData.ruleData.unshift(t);
        this.totalcount += 1;
        this.$emit("add", t);
      } else {
        let isCallback = false;
        this.$emit("add", (callback) => {
          isCallback = callback();
        });
        if (isCallback == false) {
          let vm = createForm({
            attrs: Object.assign({ formAttrs: this.tableAttrs }, this.$attrs?.form?.attrs),
            on: Object.assign({
              saveData: async (addFormData, func, that) => {
                await this.formSaveDataBack(addFormData, vm, undefined, that);
              }
            }, this.$attrs?.form?.on),
            scopedSlots: this.$attrs?.form?.scopedSlots
          })
        }
      }
    },
    //行内新增
    lineAdd(row, index) {
      opt.debounce(() => {
        let f = this.$refs.ruleForm;
        f.validate((valid, data) => {
          if (valid) {
            this.$emit("row-save", row, index);
          } else {
            console.log(data);
          }
        });
      }, 500)
    },
    //编辑
    async edit(data, index) {
      this.editIndex = index;
      let isCallBack = false;
      this.$emit(
        "edit",
        this.editTable ? data : Object.assign({}, data),
        (callback) => {
          isCallBack = callback(data);;
        },
        index
      );
      if (isCallBack == false) {
        let vm = createForm({
          attrs: Object.assign({
            formAttrs: this.tableAttrs,
            formInfo: data,
          }, this.$attrs?.form?.attrs),
          on: Object.assign({
            saveData: async (addFormData, func, that) => {
              await this.formSaveDataBack(addFormData, vm, index, that);
            }
          }, this.$attrs?.form?.on),
          scopedSlots: this.$attrs?.form?.scopedSlots
        })
      }
    },
    async formSaveDataBack(addFormData, vm, index = undefined, that = undefined) {
      let d = this.tableData.ruleData;
      let defaultResult = { isadd: false, closeForm: true, savedData: {}, resetForm: false };
      let result = await new Promise((resolve) => {
        this.$emit('saveData', addFormData, (cbResult) => {
          resolve(Object.assign(defaultResult, cbResult));
        });
      });
      if (result.closeForm) {
        vm.$destroy();
      } else {
        if (result.resetForm == true) {
          console.log(that.form);
          that.$refs.ruleForm.resetFields();
          that.form = Object.fromEntries(this.convertFormList().map((a) => [a.key, a.val]));
        }
      }
      if (result.isadd) {
        let addData = Object.assign(addFormData, result.savedData)
        if (this.globlSetting?.insertTop === false) {
          d.push(addData);
        } else {
          d.unshift(addData);
        }
        this.totalcount++;
      } else {
        try {
          d[index] = Object.assign(d[index], addFormData);
        } catch (error) {
          console.log("bus-edit" + error)
        }
      }
    },
    //查看详情
    read(data) {
      let isCallBack = false;
      this.$emit("read", data, (callback) => {
        isCallBack = callback(data);;
      });
      if (isCallBack == false) {
        createForm({
          attrs: Object.assign({
            formAttrs: this.tableAttrs,
            formInfo: data,
            showCommitBtn: false,
            isreadonly: true
          }, this.$attrs?.form?.attrs),
          on: this.$attrs?.form?.on,
          scopedSlots: this.$attrs?.form?.scopedSlots
        })
      }
    },
    //排序
    hand_order({ column, prop, order }) {
      if (this.globlSetting.handleSort && prop) {
        this.globlSetting.handleSort(this.queryInfo, prop, order);
      }
      this.page = 1;
      this.get_data_list();
    },
    //合计
    CommSum({ columns, data }) {
      if (columns && columns.length > 1) {
        let cols = columns.map((a) =>
          a && a.property ? [a.property, undefined] : ["", ""]
        );
        let sum_model = Object.fromEntries(cols);
        let values = Object.assign(sum_model, this.sumData ? this.sumData : {});
        return Object.values(values).map((m) => (m === undefined ? "" : m));
      } else {
        return [];
      }
    },
    //设置列宽
    handledrag(a, b, c) {
      if (this.resizable) {
        if (!this.widths.some((a) => a.key == c.property)) {
          this.widths.push({ key: c.property, col_width: a });
        } else {
          let obj = this.widths.find((a) => a.key == c.property);
          if (obj) {
            obj.col_width = a;
          }
        }
        let t = "colwidth" + this.$route?.name + this.suffix;
        localStorage.setItem(t, JSON.stringify(this.widths));
        let d = JSON.stringify(this.widths);
        this.debounce(() => this.globlSetting?.saveCache(t, d), 500);
        try {
          if (this.$refs["baseTable"]) {
            this.$refs["baseTable"].doLayout();
          }
        } catch (error) { }
      }
    },
    //加载列宽
    load_column_width() {
      let t = localStorage.getItem(
        "colwidth" + this.$route?.name + this.suffix
      );
      if (t) {
        this.widths = JSON.parse(t);
        this.widths.forEach((b) => {
          let temp = this.convertFormList().find((f) => f.key == b.key);
          if (temp) {
            this.$set(temp, "col_width", b.col_width);
          }
        });
      }
    },

    //展开收缩侧边栏
    toggleQuery(num) {
      let t = `${this.$route?.name}-isExpand-${this.suffix}`;
      if (num) {
        this.isExpand = false;
        localStorage.setItem(t, "0");
        this.debounce(() => this.globlSetting?.saveCache(t, "0"), 500);
      } else {
        this.isExpand = true;
        localStorage.setItem(t, "1");
        this.debounce(() => this.globlSetting?.saveCache(t, "1"), 500);
      }
    },
    //月第一天
    firstDay(date = new Date()) {
      let d = new Date(date);
      d.setDate(1);
      return d;
    },
    //点击查询更多
    more() {
      this.isMore = !this.isMore;
      this.$nextTick(() => {
        try {
          let t = document.getElementById("more").offsetHeight + 20;
          if (this.isMore) {
            this.tempHeight = `calc(100vh - ${this.height}px - ${t}px )`;
          } else {
            this.tempHeight = `calc(100vh - ${this.height}px )`;
          }
        } catch (error) {
          this.tempHeight = `calc(100vh - ${this.height}px )`;
        }
      });
    },
    //表格行选切换事件
    selectionChange(selection) {
      this.$emit("g-selection-change", selection);
    },

    //默认表格宽度
    h_width(item, w = "120px") {
      if (this.dWidth(this)) {
        if (
          item?.type != "index" &&
          item?.type != "selection" &&
          item?.type != "expand"
        )
          w = this.dWidth(this);
      }
      return !item["col_width"] ? w : item["col_width"];
    },
    /*
     *****************多选相关方法和事件*******************************************************************
     */
    //记住行
    rememberSelect(selection) {
      if (this.selectedRows.some((a) => a.index == this.page)) {
        this.selectedRows.find((a) => a.index == this.page).data = selection;
      } else {
        this.selectedRows.push({ index: this.page, data: selection });
      }
    },
    //表格行选中事件
    tableSelect(selection, row) {
      this.rememberSelect(selection);
      this.$emit("select", { selection, row, selectedRows: this.selectedRows });
    },
    //全选表格事件
    selectAll(selection) {
      this.rememberSelect(selection);
      this.$emit("g-select-all", { selection, selectedRows: this.selectedRows });
    },
    //批处理事件
    batchHandle() {
      if (this.selectedRows.length <= 0) {
        this.$message.warning("请选择要处理的数据！");
        return;
      } else {
        this.$emit("batch-handle", this.selectedRows);
      }
    },
    /*
     *****************列设置*******************************************************************
     */
    //打开列设置
    open_set() {
      this.show_set = "com-set";
    },
    //关闭列设置
    setClose() {
      this.debounce(() => this.globlSetting?.saveCache(this.$route?.name), 500);
      this.show_set = undefined;
      setTimeout(() => {
        this.$nextTick(() => {
          this.getLockRight();
        });
      }, 200);
    },
    //加载表格列，left,right
    set_columns() {
      //有设置权限
      if (this.power("setting")) {
        this.tempTableAttrs = [];
        let top = this.convertFormList().filter(
          (a) =>
            a.type == "index" || a.type == "expand" || a.type == "selection"
        );
        //位置
        let weizhi = localStorage.getItem(
          `${this.$route?.name}-position-${this.suffix}`
        );
        //列集合
        let cols = localStorage.getItem(
          `${this.$route?.name}-cols-${this.suffix}`
        );
        //列头顺序已改变
        if (weizhi) {
          if (cols) {
            let temp = [];
            let jlist = JSON.parse(cols);
            JSON.parse(weizhi)
              .filter((f) => jlist.some((s) => s == f))
              .forEach((a) => {
                let j = this.convertFormList().find(
                  (b) => b.title == a && b.visible !== false
                );
                temp.push(j);
              });
            this.tempTableAttrs = [...top, ...temp];
          } else {
            let temp = [];
            JSON.parse(weizhi).forEach((a) => {
              temp.push(
                this.convertFormList().find(
                  (b) => b.title == a && b.visible !== false
                )
              );
            });
            this.tempTableAttrs = [...top, ...temp];
          }
        }
        //列头顺序未改变
        else {
          if (cols) {
            let temp = [];
            let jlist = JSON.parse(cols);
            this.convertFormList()
              .filter((f) => jlist.some((s) => s == f.title))
              .forEach((a) => {
                temp.push(a);
              });
            this.tempTableAttrs = [...top, ...temp];
          } else {
            this.tempTableAttrs = this.convertFormList();
          }
        }
      }
      //没有设置权限
      else {
        this.tempTableAttrs = this.convertFormList();
      }
    },
    //列拖拽
    setDrag(data) {
      let t = `${this.$route?.name}-position-${this.suffix}`;
      let d = JSON.stringify(data.map((a) => a.title));
      localStorage.setItem(t, d);
      this.set_columns();
      this.loadLeft();
    },
    //设置列显示
    setColVal(vals) {
      let t = `${this.$route?.name}-cols-${this.suffix}`;
      let v = JSON.stringify(vals);
      localStorage.setItem(t, v);
      this.set_columns();
      this.loadLeft();
    },
    //加载列，列位置，列左，列右
    setLoad(back) {
      //锁左边
      let tempLock = 0;
      let lock_e = localStorage.getItem(
        `${this.$route?.name}-lock-left-${this.suffix}`
      );
      if (lock_e) {
        tempLock = parseInt(lock_e);
      } else {
        tempLock = 0;
      }
      //锁右边
      let checked = false;
      let local_right = `${this.$route?.name}-lock-right-${this.suffix}`;
      if (localStorage.getItem(local_right)) {
        checked = true;
      } else {
        checked = false;
      }
      //位置
      let weizhi = localStorage.getItem(
        `${this.$route?.name}-position-${this.suffix}`
      );
      let newPosition = [];
      if (weizhi) {
        let wz = JSON.parse(weizhi);
        wz.forEach((b) => {
          newPosition.push(
            this.convertFormList().find(
              (a) => a.title == b && a.visible !== false
            )
          );
        });
      } else {
        newPosition = this.convertFormList().filter(
          (a) =>
            a.visible !== false &&
            a.type != "index" &&
            a.type != "expand" &&
            a.type != "selection"
        );
      }
      //列集合
      let list = localStorage.getItem(
        `${this.$route?.name}-cols-${this.suffix}`
      );
      if (list) {
        return back(newPosition, JSON.parse(list), tempLock, checked);
      } else {
        let t = this.convertFormList()
          .filter(
            (a) =>
              a.visible !== false &&
              a.type != "index" &&
              a.type != "expand" &&
              a.type != "selection"
          )
          .map((a) => a.title);
        back(newPosition, t, tempLock, checked);
      }
    },
    //加载left
    loadLeft() {
      let num = localStorage.getItem(
        `${this.$route?.name}-lock-left-${this.suffix}`
      );
      if (num) {
        this.setLeft(num);
      }
    },
    //通过left 设置表格 fixed left
    setLeft(num) {
      this.tempTableAttrs.forEach((e) => {
        this.$set(e, "fixed", false);
      });
      if (num) {
        let t = parseInt(num);
        if (
          t > this.tempTableAttrs.filter((a) => a.visible !== false)?.length
        ) {
          t = this.tempTableAttrs.filter((a) => a.visible !== false)?.length;
        }
        for (let index = 0; index < t; index++) {
          const element = this.tempTableAttrs.filter(
            (a) => a.visible !== false
          )[index];
          this.$set(element, "fixed", "left");
        }
      }
    },
    //设置left
    lockLeft(val) {
      let numleft = `${this.$route?.name}-lock-left-${this.suffix}`;
      if (!val) {
        localStorage.removeItem(numleft);
      } else {
        localStorage.setItem(numleft, val);
        this.setLeft(val);
      }
    },
    //列设置复位
    rowReset() {
      this.$confirm("是否要恢复位置？", "提示消息", {
        roundButton: true,
        iconClass: "el-icon-question",
      })
        .then(() => {
          localStorage.removeItem(
            `${this.$route?.name}-lock-left-${this.suffix}`
          );
          localStorage.removeItem(
            `${this.$route?.name}-position-${this.suffix}`
          );
          localStorage.removeItem(`${this.$route?.name}-size-${this.suffix}`);
          localStorage.removeItem(
            `${this.$route?.name}-lock-right-${this.suffix}`
          );
          localStorage.removeItem(`${this.$route?.name}-cols-${this.suffix}`);
          localStorage.removeItem("colwidth" + this.$route?.name + this.suffix);
          this.tempTableAttrs = this.convertFormList();
          this.setClose();
        })
        .catch(() => {
          console.log("取消重置了");
        });
    },
    //锁右边
    lockRight(val) {
      let t = `${this.$route?.name}-lock-right-${this.suffix}`;
      if (val == true) {
        localStorage.setItem(t, "lock-right");
      } else {
        localStorage.removeItem(t);
      }
    },
    //加载锁右边
    getLockRight() {
      let t = `${this.$route?.name}-lock-right-${this.suffix}`;
      if (localStorage.getItem(t)) {
        this.isLockRight = "right";
      } else {
        try {
          if (
            hasHorizontalScrollbar(
              document.getElementsByClassName("el-table__body-wrapper")[0]
            )
          ) {
            this.isLockRight = "right";
          } else {
            this.isLockRight = false;
          }
        } catch (error) {
          this.isLockRight = false;
        }
      }
    },
    //表单验证
    init_rules(obj, form) {
      return init_rules(obj, form);
    },
    //防抖
    debounce(func, time) {
      return opt.debounce(func, time);
    },
    //分散对齐
    doJustify() {
      return this.justify(this);
    },
    //表格控制按钮对齐方式
    doControlAlign() {
      return this.controlAlign(this);
    },
    //分页条对齐方式
    doPageAlign() {
      return this.page_align(this);
    },
    filterMethod(value, row, column, item) {
      if (item["filters"] !== undefined && item["filterMethod"] === undefined) {
        const property = column["property"];
        return row[property] === value;
      } else {
        return item["filterMethod"](value, row, column, this);
      }
    },
    filters(item) {
      return item["filters"](this);
    },
    expandChange(row, expandedRows) {
      this.$emit("g-expand-change", row, expandedRows);
    },
  },
  async mounted() {
    if (this.fixedHeight !== undefined) {
      this.tempHeight = this.fixedHeight;
    } else {
      this.tempHeight = `calc(100vh - ${this.height}px)`;
    }
    this.set_columns();
    if (this.globlSetting.handleSort && this.sort && this.sort.column) {
      this.globlSetting.handleSort(
        this.queryInfo,
        this.sort.column,
        this.sort?.order
      );
    }
    await this.get_data_list();
    this.load_column_width();
    if (localStorage.getItem(`${this.$route?.name}-size-${this.suffix}`)) {
      this.pagesize = parseInt(
        localStorage.getItem(`${this.$route?.name}-size-${this.suffix}`)
      );
    }
    if (
      localStorage.getItem(`${this.$route?.name}-isExpand-${this.suffix}`) ===
      null
    ) {
      this.isExpand = true;
    } else {
      this.isExpand =
        localStorage.getItem(`${this.$route?.name}-isExpand-${this.suffix}`) ===
        "1";
    }
    if (this.row_Drop) {
      this.rowDrop();
    }
    let t = this.convertQueryList().filter((a) => a.query);
    if (t && t.length > 0) {
      t.forEach((element) => {
        this.$set(element, "dicts", [
          {
            label: element?.queryAllText ? element.queryAllText : "全部",
            value: element?.val,
          },
        ]);
      });
    }
    this.loadLeft();
    this.selectedRows = [];
    if (this.globlSetting?.queryH !== undefined) {
      this.isQueryH = this.globlSetting?.queryH;
    } else {
      this.isQueryH = this.queryH;
    }
    if (this.btnTypes) {
      for (const i of Object.keys(this.btnTypes)) {
        this.globlSetting[i].type = this.btnTypes[i]?.type;
      }
    }
    bus.$on("form-save", (data, isAdd) => {
      let d = this.tableData.ruleData;
      if (isAdd) {
        if (this.globlSetting?.insertTop === false) {
          d.push(data);
        } else {
          d.unshift(data);
        }
        this.totalcount++;
      } else {
        if (this.editIndex != -1) {
          try {
            d[this.editIndex] = Object.assign(d[this.editIndex], data);
          } catch (error) {
            console.log('form-save:' + error);
          }
        }
      }
    });
    setTimeout(() => {
      this.$nextTick(() => {
        this.getLockRight();
      });
    }, 200);
  },
  watch: {
    tableAttrs: {
      handler: function (newVal, oldVal) {
        if (newVal != oldVal) {
          this.tempTableAttrs = this.convertFormList();
        }
      },
      deep: true,
    },
  },
  updated() {
    this.$nextTick(() => {
      try {
        if (this.$refs["baseTable"]) {
          this.$refs["baseTable"].doLayout();
        }
      } catch (error) { }
    });
  },
  computed: {
    setStyle() {
      if (this.$attrs && this.$attrs.attrs && this.$attrs.attrs['min-height']) {
        return `min-height:${this.$attrs.attrs['min-height']}`
      } else {
        return `height:${this.tempHeight}`
      }
    }
  }
};
</script>

<style scoped>
.maincon {
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  width: 100% !important;
}

.funs {
  display: flex;
  align-items: center;
  padding: 3px;
}

.h-funs {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  padding: 3px;
}

.tabcon {
  display: flex;
  width: 100%;
  overflow: auto;
}

.gpage {
  display: flex;
  height: 40px;
  justify-content: center;
  align-items: center;
}

.more {
  border: 1px solid #d9d9d9;
  background: #f2f2f2;
  border-radius: 5px;
  min-height: 40px;
  display: flex;
  flex: 1;
  overflow: auto;
  padding: 20px;
  margin: 10px;
}

.fade-enter-active,
.fade-leave-active {
  transition: opacity 0.5s;
}

.fade-enter,
.fade-leave-to

/* .fade-leave-active below version 2.1.8 */
  {
  opacity: 0;
}

.query-label {
  display: inline-flex;
  height: 100%;
  align-items: center;
  margin-right: 3px;
  width: 100px;
  justify-content: flex-end;
  font-size: 12px;
  height: 36px;
  font-weight: normal;
}

.query-label-h {
  display: inline-block;
  margin-right: 3px;
  width: 100px;
  font-size: 12px;
  text-align-last: justify !important;
  height: 36px;
  line-height: 36px;
  font-weight: normal;
}

.el-table__cell .el-input__prefix div,
.el-table__cell .el-input__suffix div {
  display: inline-flex;
  align-items: center;
  height: 36px;
}
</style>

<style>
.el-form-item__error {
  position: relative !important;
}

.query-top {
  display: flex;
  flex-wrap: wrap;
  flex: 1;
}

.query-btns {
  height: 100%;
  display: flex;
  align-items: center;
  padding: 3px;
}

.query-btns button {
  margin-bottom: 3px;
}
</style>
